Skip to content

Allow advanced search to return archived questions #6631

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions kitsune/search/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ def get_highlight_fields_options(self):
...

@abstractmethod
def get_filter(self):
def get_filter(self, is_simple_search: bool):
"""A query which filters for all documents to be searched over."""
...

Expand Down Expand Up @@ -344,6 +344,10 @@ def __getitem__(self, key):
return self.results[0]
return self.results

def get_filter(self, is_simple_search: bool):
"""Placeholder for subclasses, should be implemented there."""
raise NotImplementedError
Comment on lines +347 to +349
Copy link
Preview

Copilot AI Apr 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There appear to be two implementations of get_filter in the same class, which could lead to confusion or unintended behavior. Consider consolidating these definitions into a single implementation.

Suggested change
def get_filter(self, is_simple_search: bool):
"""Placeholder for subclasses, should be implemented there."""
raise NotImplementedError
# Removed redundant get_filter method from SumoSearch class.

Copilot uses AI. Check for mistakes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • It's an abstract method in SumoSearchInterface, so all child classes (including SumoSearch) must implement it with the same signature

  • Even though SumoSearch.get_filter() just raises NotImplementedError, it needs to maintain the correct signature for consistency and to ensure proper type checking


def build_query(self):
"""Build a query to search over a specific set of documents."""
parsed = None
Expand Down Expand Up @@ -372,8 +376,9 @@ def run(self, key: Union[int, slice] = slice(0, settings.SEARCH_RESULTS_PER_PAGE
**settings.ES_SEARCH_PARAMS
)

# add the search class' filter
search = search.query(self.get_filter())
# filter method needs simple_search status
# (True for keyword search, False for advanced syntax)
search = search.query(self.get_filter(is_simple_search=not self.parse_query))
# add highlights for the search class' highlight_fields
for highlight_field, options in self.get_highlight_fields_options():
search = search.highlight(highlight_field, **options)
Expand Down
29 changes: 21 additions & 8 deletions kitsune/search/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def get_highlight_fields_options(self):
]
return [(field, FVH_HIGHLIGHT_OPTIONS) for field in fields]

def get_filter(self):
def get_filter(self, is_simple_search: bool):
filters = [
# restrict to the question index
DSLQ("term", _index=self.get_index()),
Expand All @@ -124,10 +124,12 @@ def get_filter(self):
"gte": datetime.now(timezone.utc) - timedelta(days=QUESTION_DAYS_DELTA)
},
),
# exclude archived questions
DSLQ("term", question_is_archived=False),
]

if is_simple_search:
# Only exclude archived questions in simple search
filters.append(DSLQ("term", question_is_archived=False))

if self.product:
filters.append(DSLQ("term", question_product_id=self.product.id))
return DSLQ(
Expand Down Expand Up @@ -201,13 +203,18 @@ def get_highlight_fields_options(self):
]
return [(field, FVH_HIGHLIGHT_OPTIONS) for field in fields]

def get_filter(self):
def get_filter(self, is_simple_search: bool):
# Add default filters:
filters = [
# limit scope to the Wiki index
DSLQ("term", _index=self.get_index()),
DSLQ("exists", field=f"title.{self.locale}"),
]

if is_simple_search:
# Only exclude archived documents in simple search
filters.append(DSLQ("term", is_archived=False))

if self.product:
filters.append(DSLQ("term", product_ids=self.product.id))
return DSLQ("bool", filter=filters, must=self.build_query())
Expand Down Expand Up @@ -245,7 +252,8 @@ def get_fields(self):
def get_highlight_fields_options(self):
return []

def get_filter(self):
def get_filter(self, is_simple_search: bool):
# Note: Profile search doesn't seem to have an archived status
return DSLQ(
"boosting",
positive=self.build_query(),
Expand Down Expand Up @@ -293,7 +301,7 @@ def get_settings(self):
def get_highlight_fields_options(self):
return []

def get_filter(self):
def get_filter(self, is_simple_search: bool):
# Add default filters:
filters = [
# limit scope to the Forum index
Expand Down Expand Up @@ -366,9 +374,14 @@ def get_fields(self):
def get_highlight_fields_options(self):
return self._from_children("get_highlight_fields_options")

def get_filter(self):
def get_filter(self, is_simple_search: bool):
# `should` with `minimum_should_match=1` acts like an OR filter
return DSLQ("bool", should=self._from_children("get_filter"), minimum_should_match=1)
# Pass the flag down to children filters
return DSLQ(
"bool",
should=[child.get_filter(is_simple_search) for child in self._children],
minimum_should_match=1,
)

def make_result(self, hit):
index = hit.meta.index
Expand Down